# -*- coding: utf-8 -*-

import sys

from PyQt4 import QtGui, QtCore
from guidata.dataset.datatypes import (DataSet, BeginGroup, EndGroup, BeginTabGroup, EndTabGroup)
from guidata.dataset.dataitems import ChoiceItem, FloatItem, StringItem
from guidata.dataset.qtwidgets import DataSetShowGroupBox, DataSetEditGroupBox

from define import *

class SessionPage (QtGui.QWizardPage):
    
    def __init__(self, sessions):
	self.sess_exists = True
	
	self.radio = []
	self.combo = None
	self.edit  = None
	
	self.radio_index = 0
	self.sessions = sessions
	
	QtGui.QWizardPage.__init__(self)
	self.initPage()
	self.initState()
    
    def initPage(self):
	boxlay = QtGui.QHBoxLayout(self)
        frame = QtGui.QFrame(self) # Фрейм
        frame.setFrameShape(QtGui.QFrame.StyledPanel)
        frame.setFrameShadow(QtGui.QFrame.Raised)

        gridlay = QtGui.QGridLayout(frame) # Менеджер размещения элементов во фрейме
        
        radio_group = QtGui.QGroupBox(u"Выбор расчета", frame)
        radio_lay = QtGui.QVBoxLayout(radio_group)
        self.radio.append(QtGui.QRadioButton(u"Существующий (из списка)", radio_group))
        self.radio.append(QtGui.QRadioButton(u"Создать новый", radio_group))
        for radio in self.radio:
	    self.connect(radio, QtCore.SIGNAL('clicked()'), self.radio_clicked);
        
        for i in self.radio:
	    radio_lay.addWidget(i)
        gridlay.addWidget(radio_group, 0, 0, 1, 2)
        
        sess_group = QtGui.QGroupBox(u"Существующие расчеты", frame)
        sess_lay = QtGui.QVBoxLayout(sess_group)
        self.combo = QtGui.QComboBox(sess_group)
        self.combo.addItems( tuple(self.sessions['name']) )
	self.combo.setEditable(False)
        sess_lay.addWidget(self.combo)
        gridlay.addWidget(sess_group, 1, 0, 1, 2)
        
        new_group = QtGui.QGroupBox(u"Новый расчет", frame)
        new_lay = QtGui.QVBoxLayout(new_group)
        label = QtGui.QLabel(u"Название может содержать латинские буквы, цифры, знаки \".\", \"_\", \"-\"\nи начинаться с буквы или цифры. Ограничено по длине 32 символами.", new_group)
        new_lay.addWidget(label)
        
        self.edit = QtGui.QLineEdit(u"", new_group)
        self.edit.setValidator(QtGui.QRegExpValidator(QtCore.QRegExp(u"^[a-zA-Z0-9]([-._a-zA-Z0-9]{1,31})?$"), self.edit))
        new_lay.addWidget(self.edit)
        gridlay.addWidget(new_group, 2, 0, 1, 2)
        
	boxlay.addWidget(frame)
	
    def initState(self):
	# change default state
	if len(self.sessions['name']):
	    self.sess_exists = True
	    self.radio[0].setChecked(True)
	    self.combo.setEnabled(True)
	    self.edit.setEnabled(False)
	else:
	    self.radio[-1].setChecked(True)
	    self.sess_exists = False
	    for radio in self.radio:
		radio.setEnabled(False)
	    self.combo.setEnabled(False)
	    self.edit.setEnabled(True)
	
    def getSession(self):
	if self.sess_exists:
	    return {'exists': True, 'name': unicode(self.combo.currentText()), 'index': self.combo.currentIndex()}
	else:
	    return {'exists': False, 'name': unicode(self.edit.text()), 'index': -1}
	
    def radio_clicked(self):
	current_index = -1
	for i in range(len(self.radio)):
	    if self.radio[i].isChecked():
		current_index = i
		break
	if current_index >= 0 and self.radio_index != current_index:
	    self.radio_index = current_index
	    self.edit.setEnabled(self.sess_exists)
	    self.sess_exists = not self.sess_exists
	    self.combo.setEnabled(self.sess_exists)
	    
    def validatePage(self):
	sess = self.getSession()
	if sess['name']:
	    if sess['exists']:
		return True
	    if not sess['name'] in self.sessions['name']:
		return True
	return False


class DecisionPage(QtGui.QWizardPage):

    def __init__(self):
	self.steps = []
	self.decisions = []
	self.group_decisions = []
	self.shadow_criterias = []
	
	self.current_decision = None
	self.current_group_decision = None
	self.current_shadow = None
	
	QtGui.QWizardPage.__init__(self)
	self.initPage()
	self.initState()
	
    def initPage(self):
	boxlay = QtGui.QHBoxLayout(self)
        frame = QtGui.QFrame(self) # Фрейм
        frame.setFrameShape(QtGui.QFrame.StyledPanel)
        frame.setFrameShadow(QtGui.QFrame.Raised)
        gridlay = QtGui.QGridLayout(frame) # Менеджер размещения элементов во фрейме

        step_group = QtGui.QGroupBox(u"Выбор шага", frame)
        step_lay = QtGui.QVBoxLayout(step_group)
        self.steps.append(QtGui.QRadioButton(u"Шаг 1", step_group))
        self.steps.append(QtGui.QRadioButton(u"Шаг 2", step_group))
        for i in self.steps:
	    self.connect(i, QtCore.SIGNAL('clicked()'), self.step_clicked);
	    step_lay.addWidget(i)
        gridlay.addWidget(step_group, 0, 0, 1, 2)

	shadow_group =  QtGui.QGroupBox(u"Критерий выбора решения по метода теней", frame)
	shadow_lay = QtGui.QVBoxLayout(shadow_group)
        self.shadow_criterias.append(QtGui.QRadioButton(u"Макс.мощность", shadow_group))
        self.shadow_criterias.append(QtGui.QRadioButton(u"Макс. соотв. исходу", shadow_group))
        self.shadow_criterias.append(QtGui.QRadioButton(u"Наибольший из максимумов", shadow_group))
        for i in self.shadow_criterias:
	    self.connect(i, QtCore.SIGNAL('clicked()'), self.shadow_clicked);
	    shadow_lay.addWidget(i)
        gridlay.addWidget(shadow_group, 0, 1, 1, 2)
        
        decision_group = QtGui.QGroupBox(u"Метод решения", frame)
        decision_lay = QtGui.QVBoxLayout(decision_group)
        self.decisions.append(QtGui.QRadioButton(u"Тени Мамдани", decision_group))
        self.decisions.append(QtGui.QRadioButton(u"Метод групп", decision_group))
        self.decisions.append(QtGui.QRadioButton(u"Тени Мамдани-Лукасевича", decision_group))
        
        for i in self.decisions:
	    self.connect(i, QtCore.SIGNAL('clicked()'), self.decision_clicked);
	    decision_lay.addWidget(i)
        gridlay.addWidget(decision_group, 1, 0)
        
        group_decision_group = QtGui.QGroupBox(u"Метод разбиения на группы", frame)
        group_decision_lay = QtGui.QVBoxLayout(group_decision_group)
        self.group_decisions.append(QtGui.QRadioButton(u"Мамдани-Заде", group_decision_group))
        self.group_decisions.append(QtGui.QRadioButton(u"Лукасевича", group_decision_group))
        for i in self.group_decisions:
	    group_decision_lay.addWidget(i)
        gridlay.addWidget(group_decision_group, 1, 1)
        
	boxlay.addWidget(frame)
	
    def initState(self):
	self.steps[0].setChecked(True)
	self.steps[-1].setEnabled(False)
	for i in range(len(self.decisions)):
	    self.decisions[i].setEnabled(True)
	self.decisions[0].setChecked(True)
	for i in self.group_decisions:
    	    i.setEnabled(False)
    	self.group_decisions[0].setChecked(True)
    	self.current_group_decision = 0
	self.current_shadow = 0
	for i in self.shadow_criterias:
	    i.setEnabled(True)
	self.shadow_criterias[0].setChecked(True)

    def setState(self, state=None): #state - dict
	if state == None:
	    return
	if 'step' in state:
	    for i in range(len(self.steps)):
		if i == state['step']:
		    self.steps[i].setChecked(True)
		self.steps[i].setEnabled(True)
	
	if 'decision' in state:
	    for i in range(len(self.decisions)):
		if i == state['decision']:
		    self.decisions[i].setChecked(True)
		self.decisions[i].setEnabled(False)
	
	if 'group' in state:
	    for i in range(len(self.group_decisions)):
		if i == state['group']:
		    self.current_group_decision = i
		    self.group_decisions[i].setChecked(True)
		self.group_decisions[i].setEnabled(False)
	if 'shadow' in state:
	    for i in range(len(self.shadow_criterias)):
		if i == state['shadow']:
		    self.current_shadow = i
		    self.shadow_criterias[i].setChecked(True)
		self.shadow_criterias[i].setEnabled(False)
	
    def step_clicked(self):
	is_step2 = self.steps[1].isChecked()
	if is_step2 == False: #step1
	    for i in self.group_decisions:
		i.setEnabled(is_step2)
	    if self.current_group_decision:
		self.group_decisions[ self.current_group_decision ].setChecked(True)

    def decision_clicked(self):
	current_index = -1
	for i in range(len(self.decisions)):
	    if self.decisions[i].isChecked():
		current_index = i
		break
	if current_index >= 0 and self.current_decision != current_index:
	    self.current_decision = current_index
	    if self.current_decision == eDecisions.Groups:
		for i in self.group_decisions:
		    i.setEnabled(True)
		for i in self.shadow_criterias:
		    i.setEnabled(False)
	    elif self.current_decision == eDecisions.Shadows:
		for i in self.group_decisions:
		    i.setEnabled(False)
		for i in self.shadow_criterias:
		    i.setEnabled(True)
	    elif self.current_decision == eDecisions.ShadowsML:
		for i in self.group_decisions:
		    i.setEnabled(False)
		for i in self.shadow_criterias:
		    i.setEnabled(False)
    
    def shadow_clicked(self):
	current_index = -1
	for i in range(len(self.shadow_criterias)):
	    if self.shadow_criterias[i].isChecked():
		current_index = i
		break

    def getStep(self):
	for i in range(len(self.steps)):
	    if self.steps[i].isChecked():
		return i
	return -1

    def setStep(self, idx):
	if idx < len(self.steps):
	    self.steps[idx].setChecked()

    def getDecision(self):
	for i in range(len(self.decisions)):
	    if self.decisions[i].isChecked():
		return i
	return -1

    def setDecision(self, idx):
	if idx < len(self.decisions):
	    self.decisions[idx].setChecked()

    def getGroupDecision(self):
	for i in range(len(self.group_decisions)):
	    if self.group_decisions[i].isChecked():
		return i
	return -1
	
    def setGroupDecision(self, idx):
	if idx < len(self.group_decisions):
	    self.group_decisions[idx].setChecked()
	
    def getShadow(self):
	for i in range(len(self.shadow_criterias)):
	    if self.shadow_criterias[i].isChecked():
		return i
	return -1
	
    def setShadow(self, idx):
	if idx < len(self.shadow_criterias):
	    self.shadow_criterias[idx].setChecked()
	
    def getValues(self):
	return {
	    'step'     : self.getStep(),
	    'decision' : self.getDecision(),
	    'group'    : self.getGroupDecision(),
	    'shadow'   : self.getShadow()
	}


class LP2Page (QtGui.QWizardPage):

    def __init__(self, p):
	self.combo = None
	QtGui.QWizardPage.__init__(self)
	self.initPage(p)

    def initPage(self, p):
	boxlay = QtGui.QHBoxLayout(self)
        frame = QtGui.QFrame(self) # Фрейм
        frame.setFrameShape(QtGui.QFrame.StyledPanel)
        frame.setFrameShadow(QtGui.QFrame.Raised)

        gridlay = QtGui.QGridLayout(frame) # Менеджер размещения элементов во фрейме
        
        label = QtGui.QLabel(u"ЛП2",frame)
        gridlay.addWidget(label,0,0)

	self.combo = QtGui.QComboBox(frame)
	self.combo.addItems( tuple(p) )
	self.combo.setEditable(False)
	gridlay.addWidget(self.combo,0,1)
	
	boxlay.addWidget(frame)

    def getValue(self):
	return self.combo.currentIndex()

    def setValue(self, value):
	self.combo.setCurrentIndex(value)
	
    def initState(self):
	self.setValue(0)

    def setEnabled(self, enabled=True):
	self.combo.setEnabled(enabled)


class LP1Page (QtGui.QWizardPage):

    def __init__ (self):
	self.elements = []
	self.edits = [] # values of edits
	self.init = False
	QtGui.QWizardPage.__init__(self)
	self.layout = QtGui.QHBoxLayout(self)

    def initPage(self, p):
	
	if self.init:
	    return
	
	scroll = QtGui.QScrollArea(self)
	self.elements.append(scroll)
        frame = QtGui.QFrame(scroll) # Фрейм
        
        self.elements.append(frame)
        frame.setFrameShape(QtGui.QFrame.StyledPanel)
        frame.setFrameShadow(QtGui.QFrame.Raised)

        gridlay = QtGui.QGridLayout(frame) # Менеджер размещения элементов во фрейме
        self.elements.append(gridlay)
        
        label = QtGui.QLabel(u'Значения в интервале [0, 1]; -1 - не использовать переменную в расчетах', frame)
        self.elements.append(label)
        gridlay.addWidget(label, 0, 0, 1, 2)
        
        k = 1
        for i in tuple(p):
    	    label = QtGui.QLabel(i, frame)
    	    self.elements.append(label)
    	    edit = QtGui.QLineEdit('0.0', frame)
    	    edit.setValidator(QtGui.QRegExpValidator(QtCore.QRegExp(u"^((0\.\d{1,4})|(1(\.0{1,4})?)|\-1)$"), edit))
    	    self.edits.append(edit)
    	    gridlay.addWidget(label, k, 0)
    	    gridlay.addWidget(edit, k, 1)
    	    k = k + 1

	self.layout.addWidget(scroll)
	scroll.setWidget(frame)
	self.init = True

    def cleanPage (self):
	if not self.init:
	    return

	if len(self.elements):
	    self.layout.removeWidget(self.elements[0])
	    self.elements[0].setParent(None)
	
	for elem in self.elements:
	    del elem
	    
	for edit in self.edits:
	    del edit
	    
	self.elements = []
	self.edits = []
	self.init = False

    def isInit (self):
	return self.init

    def getEdits(self):
	return self.edits


class Wizard (QtGui.QWizard):

    def __init__ (self, sessions, param):
	self._vars = param
	# страницы
	self.pages = {}	
	# индексы в массиве решений и методов
	self.indexes = {}
	# сохраненное состояние
	self.state = {'step': -1}
	
	self.sessions = sessions
	
	QtGui.QWizard.__init__(self)
	self.initPages()

    def initPages (self):
	#lp2 names
	lp2 = self._vars['list'].keys()
	lp2_names = []
	for i in lp2: 
	    lp2_names.append(self._vars['set'][i]['name'])
	    
	#pages
	self.pages['session']  = SessionPage(self.sessions)
	self.pages['decision'] = DecisionPage()
	self.pages['lp2']      = LP2Page(lp2_names)
	self.pages['lp1']      = LP1Page()
	
	# add pages to the wizard
	self.indexes['page_session']  = self.addPage(self.pages['session'])
	self.indexes['page_decision'] = self.addPage(self.pages['decision'])
	self.indexes['page_lp2']      = self.addPage(self.pages['lp2'])
	self.indexes['page_lp1']      = self.addPage(self.pages['lp1'])

    def nextId (self):
	if self.currentId() == self.indexes['page_session']:
	    pass
	elif self.currentId() == self.indexes['page_decision']:
	    session = self.pages['session'].getSession()
	    
	    if self.state['step'] < self.indexes['page_session']:
		self.state['step']  = self.indexes['page_session']
		self.state['session'] = session
		self.currentPage().initState()
		#load session data
		if session['exists']:
		    session_data = self.sessions['data'][ session['index'] ]
		    if session_data:
			self.pages['decision'].setState(session_data)
		    
	    elif self.state['session'] != session:
		self.state['step']  = self.indexes['page_session']
		self.state['session'] = session
		self.currentPage().initState()
		#load session data
		if session['exists']:
		    session_data = self.sessions['data'][ session['index'] ]
		    if session_data:
			self.pages['decision'].setState(session_data)
	    
	elif self.currentId() == self.indexes['page_lp2']:
	    decision = self.pages['decision'].getValues()
	    
	    if self.state['step'] < self.indexes['page_decision']:
		self.state['step']  = self.indexes['page_decision']
		self.state['decision'] = decision
		self.currentPage().initState()
	    elif self.state['decision'] != decision:
		self.state['step']  = self.indexes['page_decision']
		self.state['decision'] = decision
		self.currentPage().initState()
		
	    self.currentPage().setEnabled(True)
	    if decision['step'] == 1: # step 2
		self.currentPage().setEnabled(False)
		return -1
		
	elif self.currentId() == self.indexes['page_lp1']:
	    lp2 = self.pages['lp2'].getValue()
	    rebuild = False
	
	    if self.state['step'] < self.indexes['page_lp2']:
		self.state['step']  = self.indexes['page_lp2']
		self.state['lp2'] = lp2
		rebuild = True
	    elif self.state['lp2'] != lp2:
		self.state['step']  = self.indexes['page_lp2']
		self.state['lp2'] = lp2
		rebuild = True
	
	    if rebuild:
		self.pages['lp1'].cleanPage()
		#lp1 names
		lp2_list = self._vars['list'].keys()
		lp2_name = lp2_list[lp2]
		lp1_names = []
		for i in self._vars['list'][lp2_name]:
		    lp1_names.append(self._vars['set'][i]['name'])
		self.pages['lp1'].initPage(lp1_names)
	
	return QtGui.QWizard.nextId(self)

    def done (self, result):
	ret = 1
	self.state['values'] = {}
	
	if 1 == result: #done
	    #test values
	    edits = self.pages['lp1'].getEdits()
	    for e in edits:
		if not e.hasAcceptableInput():
		    ret = 0
		    break
	    #store values
	    if ret:
		try:
		    lp2_list = self._vars['list'].keys()
		    lp2_name = lp2_list[self.state['lp2']]
		    # ЛП2
		    self.state['lp2'] = lp2_name
		    # значения ЛП1
		    for i in range(0, len(edits)):
			name = self._vars['list'][lp2_name][i]
			val = float(edits[i].text())
			self.state['values'][name] = val
		except Exception, e:
		    pass
		finally:
		    self._vars['state'] = self.state
	    else:
		self._vars.pop('state', '')
	else:
	    self._vars.pop('state', '')
	    
	if ret:
	    return QtGui.QWizard.done(self, result)


class Dialog:

    def __init__ (self, sessions, param, w=480, h=320):
	app = QtGui.QApplication(sys.argv)
	wizard = Wizard(sessions, param)
	wizard.resize(w, h)
	wizard.show()
	app.exec_()

